package com.xiaow.springsecuriydemo.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaow.springsecuriydemo.entity.Goods;
import com.xiaow.springsecuriydemo.entity.Trading;
import com.xiaow.springsecuriydemo.service.GoodsService;
import com.xiaow.springsecuriydemo.service.TradingService;
import com.xiaow.springsecuriydemo.utils.JwtUtils;
import com.xiaow.springsecuriydemo.vo.*;
import io.jsonwebtoken.Claims;
import org.apache.logging.log4j.util.Strings;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author xiaow
 * @since 2022-09-17
 */
@RestController
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    private GoodsService goodsService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TradingService tradingService;

    /**
     * 添加货品
     *
     * @param goods
     * @param httpServletRequest
     * @return
     */
    @PostMapping("/addGoods")
    @PreAuthorize("hasAuthority('/shoper')")
    public Result addGoods(@RequestBody Goods goods, HttpServletRequest httpServletRequest) {
        goods.setCtime(LocalDateTime.now());
        goods.setRemaining(goods.getSize());
        goods.setState(0);
        boolean save = goodsService.save(goods);

        if (save) {
            return Result.succ("添加成功");
        } else {
            return Result.fail("添加失败，请稍后重试");
        }
    }


    /**
     * 拿到所有的货物
     *
     * @return
     */

    @GetMapping("/getAllGoods")
    public Result getAllGoods(@RequestParam(name = "state", required = false, defaultValue = "0") Integer state) {
        List<GoodVo> allGoods = goodsService.getAllGoods(state);
        return Result.succ(allGoods);
    }

    /**
     * 根据货物id拿到货物
     *
     * @param id
     * @return
     */
    @GetMapping("/getGoodsById")
    public Result getGoodsById(Integer id) {
        GoodVo oneById = goodsService.getOneById(id);
        return Result.succ(oneById);
    }


    /**
     * 根据货物id拿到货物
     *
     * @param id
     * @return
     */
    @GetMapping("/getSeckillById")
    public Result getSeckillById(Integer id) {
        Object o = redisTemplate.opsForValue().get("seckill" + id);
        Goods byId = goodsService.getOneById(id);
        if (Objects.isNull(o)) {
//            还未开始
            byId.setState(2);
        } else {
//            String remainings= (String) o;
            Integer remaining = (Integer) o;
            byId.setRemaining(remaining);
        }
        return Result.succ(byId);
    }


    /**
     * 秒杀商品购买
     *
     * @return
     */
    @PostMapping("/buySeckill")
    @PreAuthorize("hasAuthority('/user')")
//    @Transactional
    public Result buySeckill(@RequestBody Goods goods) {
        System.out.println(goods);

        Goods byId = goodsService.getById(goods.getId());
        String key = "seckill" + goods.getId();
        Object o1 = redisTemplate.opsForValue().get("seckill" + goods.getId());
        if (Objects.isNull(o1))
            return Result.fail("还未开始抢购");

        redisTemplate.watch("seckill" + goods.getId());
        redisTemplate.multi();
        Integer remaining = (Integer) o1;
        if (remaining <= 0) {
            goodsService.updateById(byId.setState(3));
            return Result.fail("抢完了");
        }
        redisTemplate.opsForValue().set("seckill" + goods.getId(), remaining - 1);
        List exec = redisTemplate.exec();
        if (exec == null) {
            return Result.fail("请稍后重试，抢购失败");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();

        byId.setRemaining(byId.getRemaining() - 1);
//        更新数据库中的库存量
        boolean b = goodsService.updateById(byId);
//        加入订单
        Trading trading = new Trading()
                .setCtime(LocalDateTime.now())
                .setGoodsid(goods.getId())
                .setMoney(byId.getMoney())
                .setStatus(0)
                .setId(0)
                .setUserid(loginUser.getUser().getId());
        boolean save = tradingService.save(trading);
        return Result.succ("抢购成功");
    }


    /**
     * 添加秒杀商品
     */
    @PostMapping("/addSeckill")
    @PreAuthorize("hasAuthority('/shoper')")
    public Result addSeckill(@RequestBody Goods goods) {

//        货品state为1代表秒杀产品   初试库存量等于所有的量
        goods.setState(1)
                .setRemaining(goods.getSize());
        boolean save = goodsService.save(goods);
        if (!save)
            throw new RuntimeException();
//        为cronTrigger做准备
        LocalDateTime ctime = goods.getCtime();
        int year = ctime.getYear();
        int value = ctime.getMonth().getValue();
        int dayOfMonth = ctime.getDayOfMonth();
        int hour = ctime.getHour();
        int minute = ctime.getMinute();
//        CronTrigger设置时间的语法   秒 分  时  天  月 ？ 年
        String rtime = "0 " + minute + " " + hour + " " + dayOfMonth + " " + value + " ? " + year;
//        设置crontrigger
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job" + LocalDateTime.now().toString(), "seckillgroup1")
                .usingJobData("info", goods.getId().toString())
                .usingJobData("size", goods.getSize().toString())
                .build();

        CronTrigger trigger = (CronTrigger) TriggerBuilder.newTrigger()
                .withIdentity("myTrigger" + LocalDateTime.now().toString(), "triggergroup1")
                .withSchedule(
                        CronScheduleBuilder.cronSchedule(rtime)
                ).build();
        try {
            Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();
            defaultScheduler.scheduleJob(jobDetail, trigger);
            defaultScheduler.start();

        } catch (SchedulerException e) {
            e.printStackTrace();
            return Result.fail("添加失败");
        }
        return Result.succ("添加成功");
    }

    /**
     * 获取所有的秒杀商品
     *
     * @return
     */
    @GetMapping("/getAllSeckillGoods")
    public Result getAllSeckillGoods() {
        List<GoodVo> list = goodsService.getAllGoods(1);
        list.forEach(g -> {
            Object o = redisTemplate.opsForValue().get("seckill" + g.getId());
            if (Objects.isNull(o)) {
//                代表还没开始抢购
                g.setState(2);
            }
        });
        list.sort((Goods good1, Goods good2) -> {
            return good1.getState() - good2.getState();
        });
        return Result.succ(list);
    }

    /**
     * 商家退货
     *
     * @param trading
     * @return
     */
    @PostMapping("/returnGoods")
    @PreAuthorize("hasAuthority('/shoper')")
    @Transactional
    public Result returnGoods(@RequestBody Trading trading) {
        Goods byId = goodsService.getById(trading.getGoodsid());
        Goods goods = byId.setRemaining((int) (byId.getRemaining() + trading.getMoney() / byId.getMoney()) + byId.getRemaining());
        goodsService.updateById(byId);
        tradingService.updateById(new Trading().setId(trading.getId()).setStatus(1));
        return Result.succ("退货成功");
    }


    /**
     * 商家下架商品
     *
     * @param goods
     * @return
     */
    @PostMapping("/downGoods")
    @PreAuthorize("hasAuthority('/shoper')")
    public Result downGoods(@RequestBody Goods goods) {
        boolean b = goodsService.removeById(goods.getId());
        if (b)
            return Result.succ("下架商品成功");
        return Result.fail("下架商品失败，请稍后重试");
    }


    /**
     * 根据商店id获取货品列表
     * @param shopid
     * @param page
     * @param limit
     * @return
     */

    @GetMapping("/getAllByShopId")
    @PreAuthorize("hasAuthority('/shoper')")
    public LayuiPageResult getAllByShopId(@RequestParam("shopid") Integer shopid, @RequestParam(name = "page", defaultValue = "1") Integer page, @RequestParam(name = "limit", defaultValue = "10") Integer limit) {
        QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
        IPage<Goods> p = new Page<>(page, limit);
        goodsQueryWrapper.eq("shopid", shopid);
        goodsQueryWrapper.eq("state", 0);
        goodsQueryWrapper.orderByDesc("ctime");
        IPage<Goods> page1 = goodsService.page(p, goodsQueryWrapper);
        LayuiPageResult succ = new LayuiPageResult()
                .setMsg("成功")
                .setData(page1.getRecords())
                .setCode(0)
                .setCount(page1.getTotal());
        return succ;

    }



    @GetMapping("/getAllByShopIdAll")
    public LayuiPageResult getAllByShopIdAll(@RequestParam("shopid") Integer shopid, @RequestParam(name = "page", defaultValue = "1") Integer page, @RequestParam(name = "limit", defaultValue = "10") Integer limit
    ,@RequestParam(name = "state", defaultValue = "0") Integer state) {
        QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
        IPage<Goods> p = new Page<>(page, limit);
        goodsQueryWrapper.eq("shopid", shopid);
        goodsQueryWrapper.eq("state", state);
        goodsQueryWrapper.orderByDesc("ctime");
        IPage<Goods> page1 = goodsService.page(p, goodsQueryWrapper);
        LayuiPageResult succ = new LayuiPageResult()
                .setMsg("成功")
                .setData(page1.getRecords())
                .setCode(0)
                .setCount(page1.getTotal());
        return succ;

    }


}
